﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace MoFramework
{
    public class EventManager : BaseManager<EventManager>
    {

        Dictionary<int, List<Action<BaseEventArg>>> m_TypeHashFuncDict;
        Dictionary<int, List<Action<BaseEventArg>>> m_RemovedFuncDict;
        List<EventData> m_DelayTriggerEventList;
        bool m_RemoveDirty;

        #region 流程
        public EventManager():base()
        {
            m_TypeHashFuncDict = new Dictionary<int, List<Action<BaseEventArg>>>();
            m_RemovedFuncDict = new Dictionary<int, List<Action<BaseEventArg>>>();
            m_DelayTriggerEventList = new List<EventData>();
        }
        protected override void OnUpdate()
        {
            base.OnUpdate();
            ClearUnRegistFunc();
            TrigEventCurFrame();
        }
        #endregion

        #region 事件管理
        List<Action<BaseEventArg>> GetFuncListByTypeHash(int typeHash)
        {
            List<Action<BaseEventArg>> eventFunc;
            if(! m_TypeHashFuncDict.TryGetValue(typeHash, out eventFunc))
            {
                eventFunc = new List<Action<BaseEventArg>>();
                m_TypeHashFuncDict[typeHash] = eventFunc;
            }
            return eventFunc;
        }
        List<Action<BaseEventArg>> GetRemovedFuncListByTypeHash(int typeHash)
        {
            List<Action<BaseEventArg>> eventFunc;
            if (!m_RemovedFuncDict.TryGetValue(typeHash, out eventFunc))
            {
                eventFunc = new List<Action<BaseEventArg>>();
                m_RemovedFuncDict[typeHash] = eventFunc;
            }
            return eventFunc;
        }
        public T GetEventArrg<T>() where T:BaseEventArg
        {
            T arg = null;
            return arg;
        }
        public void RegistFunc<T>(Action<BaseEventArg> func) where T:BaseEventArg
        {
            Type theType = typeof(T);
            List<Action<BaseEventArg>> listFunc = GetFuncListByTypeHash(theType.GetHashCode().GetHashCode());
            listFunc.Add(func);
        }
        public void UnRegistFunc<T>(Action<BaseEventArg> func) where T : BaseEventArg
        {
            m_RemoveDirty = true;
            Type theType = typeof(T);
            List<Action<BaseEventArg>> listFunc = GetRemovedFuncListByTypeHash(theType.GetHashCode().GetHashCode());
            listFunc.Add(func);
        }
        void InternalUnRegistFunc(int hashCode,Action<BaseEventArg> func)
        {
            List<Action<BaseEventArg>> listFunc = GetFuncListByTypeHash(hashCode);
            listFunc.Remove(func);
        }
        void ClearUnRegistFunc()
        {
            if (!m_RemoveDirty) return;
            foreach (var funcKeyValues in m_RemovedFuncDict)
            {
                int key = funcKeyValues.Key;
                foreach (var func in funcKeyValues.Value)
                {
                    InternalUnRegistFunc(key, func);
                }
                funcKeyValues.Value.Clear();
            }
            m_RemoveDirty = false;
        }
        #endregion
        #region 事件触发
        void TrigEventCurFrame()
        {
            foreach(var trigEvent in m_DelayTriggerEventList)
            {
                TrigFuncRightNow(trigEvent.hashCode,trigEvent.eventArg);
            }
            m_DelayTriggerEventList.Clear();
        }
        public void TrigFuncRightNow<T>(T arg)where T:BaseEventArg
        {
            int hashCode = typeof(T).GetHashCode();
            TrigFuncRightNow(hashCode, arg);
        }
        public void TrigFuncRightNow<T>( int hashCode, T arg) where T : BaseEventArg
        {
            ClearUnRegistFunc();
            Type theType = typeof(T);
            List<Action<BaseEventArg>> listFunc = GetFuncListByTypeHash(hashCode);
            foreach (var func in listFunc)
            {
                func(arg);
            }
            ClearUnRegistFunc();
        }
        public void TrigEvent<T>(T arg)where T:BaseEventArg
        {
            int typeHashCode = typeof(T).GetHashCode();
            m_DelayTriggerEventList.Add(new EventData() { hashCode = typeHashCode, eventArg = arg });
        }
        #endregion
    }
}

